package com.calc;


import java.math.RoundingMode;
import java.util.regex.Pattern;

import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.calc.common.Constants;
import com.calc.setting.SeniorCalcSettingActivity;
import com.calc.utils.CalcUtils;

public class SeniorCalcActivity extends BaseActivity {
	
	private static final String TAG = "SeniorCalcActivity";

    //输入界面为空
    static final int FLAG_EMPTY = 0;
    //第一次没有计算前，既输入界面上只有数字
    static final int FLAG_NOT_EMPTY = 1;
    //计算完成后
    static final int FLAG_CALCULATE_FINISH = 2;

    static final int FLAG_EQUAL = 10;

    static final int FLAG_PLUS = 11;
    static final int FLAG_MINUS = 12;
    static final int FLAG_MULTIPLY = 13;
    static final int FLAG_DIVIDE = 14;
    static final int FLAG_POWER = 15;
    static final int FLAG_POWER_ROOT = 49;

    static final int FLAG_SIN = 50;
    static final int FLAG_COS = 51;
    static final int FLAG_TAN = 52;
    static final int FLAG_FACTORIAL = 99;

    //处理删除事件的标志
    static final int FLAG_DELETE = 100;
    
    //除不尽时默认小数位数
    static final String DIVIDE_DEFAULT_SCALE = "6";
    //默认尾数舍入方式
    static final String DIVIDE_DEFAULT_ROUND_MODE = "0";

    //1-9  点
    private Button num0, num1, num2, num3, num4, num5, num6, num7, num8, num9, point;

    //加减乘除等  n次方 开方 阶乘
    private Button plus, minus, multiply, divide, power,powerRoot, equal;
    private Button sin, cos, tan, nLoop;

    //回删
    private Button backspace;

    private TextView answerValue;
    String answerText;
    //存储两个操作数
    String value1,value2;
    //存储四则运算符号
    int flag = FLAG_EMPTY;
    int flag2 = FLAG_DELETE;
    //判断有无除零溢出
    boolean over = true;
    String answer = "";

    private SharedPreferences mPrivatePreferences = null;
    String scale = DIVIDE_DEFAULT_SCALE;
    RoundingMode mode = null;
    int triangleInpuType = 0;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //禁止横屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.senior_calculator);//显示界面

        initView();
        mPrivatePreferences = this.getPreferences(MODE_PRIVATE);
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        //获取计算器设置
        scale = sp.getString("general_calc_scale", DIVIDE_DEFAULT_SCALE);
    	String roundMode = sp.getString("general_calc_round_mode", DIVIDE_DEFAULT_ROUND_MODE);
        mode = getRoundingMode(roundMode);
        //获取三角函数设置
        String triangleInpuTypeStr = sp.getString("general_calc_triangle_input_type", String.valueOf(triangleInpuType));
        triangleInpuType = Integer.parseInt(triangleInpuTypeStr);
        
        plus.setOnClickListener(btnClicked);
        minus.setOnClickListener(btnClicked);
        multiply.setOnClickListener(btnClicked);
        divide.setOnClickListener(btnClicked);
        power.setOnClickListener(btnClicked);
        powerRoot.setOnClickListener(btnClicked);
        sin.setOnClickListener(btnClicked);
        cos.setOnClickListener(btnClicked);
        tan.setOnClickListener(btnClicked);
        nLoop.setOnClickListener(btnClicked);
        num0.setOnClickListener(btnClicked);
        num1.setOnClickListener(btnClicked);
        num2.setOnClickListener(btnClicked);
        num3.setOnClickListener(btnClicked);
        num4.setOnClickListener(btnClicked);
        num5.setOnClickListener(btnClicked);
        num6.setOnClickListener(btnClicked);
        num7.setOnClickListener(btnClicked);
        num8.setOnClickListener(btnClicked);
        num9.setOnClickListener(btnClicked);
        point.setOnClickListener(btnClicked);

        equal.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.v("BEFORE VALUE",String.format("value1=%s,value2=%s,answer=%s",value1,value2,String.valueOf(answer)));
                calculate();
                Log.v("AFTER VALUE",String.format("value1=%s,value2=%s,answer=%s",value1,value2,String.valueOf(answer)));
                flag = FLAG_CALCULATE_FINISH;
                flag2 = FLAG_CALCULATE_FINISH;
            }
        });
        backspace.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                answerText = answerValue.getText().toString();
                //输入界面有内容时的情况
                if(answerText.length()>0) {
                    //没有输入任何符号前的删除事件 或者 计算完成后不允许删除
                    if(flag == FLAG_EMPTY || flag== FLAG_CALCULATE_FINISH) {
                        return ;
                    } else if(flag == FLAG_NOT_EMPTY) {
                        value1 = getDeletedValue(value1);
                        answerValue.setText(answerText.substring(0,answerText.length()-1));
                    } else if(flag >= FLAG_PLUS && flag <= FLAG_FACTORIAL && !Pattern.matches(".*\\d$",answerText)) {
                        //输入了符号后没有输入数字即按下删除键
                        //如果flag2为FLAG_CALCULATE_FINISH则表示之前已经进行过运算，否则表示尚无进行运算
                        flag = (flag2 == FLAG_CALCULATE_FINISH) ? FLAG_CALCULATE_FINISH : FLAG_NOT_EMPTY;
                        answerValue.setText(answerText.substring(0,answerText.length()-3));
                    } else if(flag >= FLAG_PLUS && flag <= FLAG_FACTORIAL && Pattern.matches(".*\\d$",answerText)) {
                        //已经输入了符号，并在在符号后面再次输入了数字，这时就要处理value2的值，而flag标志位不需要改变
                        value2 = value2.substring(0, value2.length()-1);
                        answerValue.setText(answerText.substring(0,answerText.length()-1));
                    }
                }
                Log.v("LOG DELETE",String.format("flag=%s, value1=%s, value2=%s",String.valueOf(flag), value1, value2));
            }
        });
    }

    private RoundingMode getRoundingMode(String roundMode) {
        RoundingMode m = null;
        switch(Integer.parseInt(roundMode)){
            case 0:
                //四舍五入，尾数>=0.5进位，否则舍弃
                m = RoundingMode.HALF_UP;
                break;
            case 1:
                //尾数>0.5进位，否则舍弃
                m = RoundingMode.HALF_DOWN;
                break;
            case 2:
                //尾数无论如何舍弃
                m = RoundingMode.DOWN;
                break;
            case 3:
                //尾数无论如何进位
                m = RoundingMode.UP;
                break;  
            default:
                m = null;
                break;
        }
        return m;
    }

    Button.OnClickListener btnClicked = new OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.plus :
                    operation2Num(FLAG_PLUS);
                    break;
                case R.id.minus :
                    operation2Num(FLAG_MINUS);
                    break;
                case R.id.multiply:
                    operation2Num(FLAG_MULTIPLY);
                    break;
                case R.id.divide:
                    operation2Num(FLAG_DIVIDE);
                    break;
                case R.id.power:
                    operation2Num(FLAG_POWER);
                    break;
                case R.id.power_root:
                    operation2Num(FLAG_POWER_ROOT);
                    break;
                case R.id.sin:
                    operation1Num(FLAG_SIN);
                    break;
                case R.id.cos:
                    operation1Num(FLAG_COS);
                    break;
                case R.id.tan:
                    operation1Num(FLAG_TAN);
                    break;
                case R.id.factorial:
                    operation1Num(FLAG_FACTORIAL);
                    break;
                case R.id.num0 :
                case R.id.num1 :
                case R.id.num2 :
                case R.id.num3 :
                case R.id.num4 :
                case R.id.num5 :
                case R.id.num6 :
                case R.id.num7 :
                case R.id.num8 :
                case R.id.num9 :
                case R.id.point :
                    setNumText(view);
                    break;
                default:
                    ;
            }
        }
    };

    /**
     * 处理两个操作数的进行的运算
     * deal operation which needs tow operate number
     * @param o 操作标志 即: flag
     */
    //TODO 计算log
    private void operation2Num(int o) {
        String symbol = getSymbolByFlag(o);
        if(flag == FLAG_EMPTY) {
            //输入界面为空时按下加号键，不做任何操作
        } else if(flag >= FLAG_PLUS && flag <= FLAG_POWER_ROOT){
            /*
                如果按下了其他符号之后再按下加号键，则将其他符号删除，追加 加号
                这里有一种情况，既按下加号后，又按了其他数字，此时标志位是FLAG_PLUS
                例如： 1 + 2 = 3 + 5， 若此时按下减号，需要计算后再进行标志位赋值
             */
            answerText = answerValue.getText().toString();
            if(Pattern.matches(".* "+symbol, answerText.trim())) {
                //如果输入框内现有内容以+结尾，则再次按下+不做任何操作
                return ;
            } else if(Pattern.matches(".*\\d$", answerText.trim())){
                //以数字结尾的时候先计算，再追加符号
                calculate();
                //计算结束后输入框中内容改变，需要重新获取
                answerText = answerValue.getText().toString();
                answerValue.setText(answerText + " "+symbol+" ");
            } else {
                answerText = answerText.substring(0, answerText.length() - 3);
                answerValue.setText(answerText + " "+symbol+" ");
            }
            flag = o;
        } else if (flag == FLAG_CALCULATE_FINISH || value1.length() > 0) {
            //在上一次计算完成，将得到结果作为value1后继续操作 或者 第一个操作数已经存在
            //value1.length()>0 包括了FLAG_NOT_EMPTY的情况
            //如果标志位是 FLAG_CALCULATE_FINISH，则说明value1的值是上次计算完成后的值，否则即为正常输入的值
            if(flag == FLAG_CALCULATE_FINISH) {
                value1 = String.valueOf(answer);
            }
            //在存在第一个操作数的情况下将标志位设置为 FLAG_PLUS
            flag = o;
            answerText = answerValue.getText().toString();
            answerValue.setText(answerText + " "+symbol+" ");
        } else if(value1.length() > 0 && value2.length() > 0) {
            //两个操作数都存在则进行计算
            calculate();
        }
    }

    /**
     * 处理只有一个操作数的情况
     * @param o  --> flag
     */
    private void operation1Num(int o) {
        answerText = answerValue.getText().toString();
        if(flag == FLAG_EMPTY){
            //输入界面为空时，不做任何操作
            return ;
        } else if(flag == FLAG_NOT_EMPTY) {
            //处理输入框中的内容只有数字时的情况
            flag = o;
            if("!".equals(getSymbolByFlag(o))) {
                answerValue.setText(answerText + "!");
            } else {
                //sin cos tan
                answerValue.setText(getSymbolByFlag(o) + answerText);
            }
            calculate();
        } else if(flag>=FLAG_PLUS && flag < FLAG_SIN){
            //两个操作数的情况不做任何操作
            return;
        } else if(flag == FLAG_CALCULATE_FINISH){
            flag = o;
            //处理计算完成后，再进行的单操作数运算
            if("!".equals(getSymbolByFlag(o))) {
                answerValue.setText(answerText + "!");
            } else {
                //sin cos tan
                answerValue.setText(answerText + "\n" +getSymbolByFlag(o) + answer);
            }
            calculate();
        }
    }

    /**
     * 通过标志获取符号
     * @param oper
     * @return  ×÷＋－
     */
    private String getSymbolByFlag(int oper) {
        String symbol = "";
        switch (oper) {
            case FLAG_PLUS:
                symbol = "＋";
                break;
            case FLAG_MINUS:
                symbol = "－";
                break;
            case FLAG_MULTIPLY:
                symbol = "×";
                break;
            case FLAG_DIVIDE:
                symbol = "÷";
                break;
            case FLAG_POWER:
                symbol = "^";
                break;
            case FLAG_POWER_ROOT:
                symbol = "√";
                break;
            case FLAG_SIN:
                symbol = "sin";
                break;
            case FLAG_COS:
                symbol = "cos";
                break;
            case FLAG_TAN:
                symbol = "tan";
                break;
            case FLAG_FACTORIAL:
                symbol = "!";
                break;
            default:
                break;
        }

        return symbol;
    }

    private String getDeletedValue(String text) {
        return text.substring(0, text.length()-1);
    }
    private void checkInput() {
        if(".".equals(value1)) {
            value1 = "0";
        } else if(Pattern.matches("^\\.", value1)) {
            value1 = "0" + value1;
        }
        if(".".equals(value2)) {
            value2 = "0";
        } else if(Pattern.matches("^\\.", value2)) {
            value2 = "0" + value2;
        }
    }
    
    /**
     * 进行计算
     */
    private void calculate() {
        if(flag >= FLAG_PLUS && flag <= FLAG_FACTORIAL || flag == FLAG_NOT_EMPTY) {
            //如果用户只输入一个.，则认为用户输入0，如果用户输入.123这样格式的内容，则认为用户输入的是0.123
            checkInput();
            /**
             * 计算--------------------->开始
             */
            //当只有一个操作数时按下等号
            if(value1.length() > 0 && value2.length() == 0 && flag < FLAG_SIN) {
                answer = value1;
                return;
            }
            //计算结束后将value1 和 value2 的值清空，此时再次输入符号和数字点击等号后，value1为空
            if(value1.length() == 0) {value1 = String.valueOf(answer);}
            double a=0f,b=0f;
            a=Double.parseDouble(value1);
            if(flag < FLAG_SIN) {
                //只有处理两个操作数时才给b赋值
                b=Double.parseDouble(value2);
            }
            switch (flag){
                case FLAG_PLUS:
                    answer = CalcUtils.add(a, b);
                    setValue();
                    break;
                case FLAG_MINUS:
                    answer = CalcUtils.minus(a, b);
                    setValue();
                    break;
                case FLAG_MULTIPLY:
                    answer = CalcUtils.multiply(a, b);
                    setValue();
                    break;
                case FLAG_DIVIDE:
                    if(b == 0){
                        return ;
                    } else{
                        answer =  CalcUtils.divide(a, b, Integer.parseInt(scale), mode);
                        setValue();
                    };
                    break;
                case FLAG_POWER :
                    answer = CalcUtils.pow(a, b);
                    setValue();
                    break;
                case FLAG_POWER_ROOT:
                	if(b!=0) {
                		answer = CalcUtils.powRoot(a, b);
                    	setValue();
                	}
                    break;
                case FLAG_FACTORIAL:
                    //负整数不能进行阶乘
                    //vv即value1对应的正整数
                    String vv = value1.substring(1,value1.length());
                    if((value1.startsWith("-")&&Pattern.matches("\\d+", vv)) || (value1.startsWith("-")||vv.endsWith(".0"))) {
                        //两种情况  -5   或   -5.0
                        return ;
                    } else if(Pattern.matches("\\d+",String.valueOf(a)) || String.valueOf(a).endsWith(".0")) {
                        //进行阶乘的数是正整数
                        answer = CalcUtils.getFactorial((int)a);
                    } else if(value1.indexOf(".")>0 && !value1.endsWith(".0")){
                        //进行阶乘的数是小数
                        answer = CalcUtils.getFactorial((int)a);
                    }
                    setValue();
                    break;
                case FLAG_SIN:
                    answer = CalcUtils.sin(a, triangleInpuType);
                    setValue();
                    break;
                case FLAG_COS:
                    answer = CalcUtils.cos(a, triangleInpuType);
                    setValue();
                    break;
                case FLAG_TAN:
                    answer = CalcUtils.tan(a, triangleInpuType);
                    setValue();
                    break;
                default:
                    break;
            }
            answerText = answerValue.getText().toString();
            if(String.valueOf(answer).endsWith(".0")) {
                answerValue.setText(answerText + " = " + String.valueOf(answer).substring(0, String.valueOf(answer).length() -2));
            } else {
                answerValue.setText(answerText + " = " + String.valueOf(answer));
            }
        }
    }


    /**
     * 计算完成后将value1和value2的值清空，并将标志位设置为 FLAG_CALCULATE_FINISH
     */
    private void setValue() {
        value1 = "";
        value2 = "";
        flag = FLAG_CALCULATE_FINISH;
        flag2 = FLAG_CALCULATE_FINISH;
    }
    private void setNumText(View view){
        //如果当前内容最后一位是.，则再次输入点不做任何操作
        if(!(Pattern.matches(".*\\.$",String.valueOf(answerValue.getText().toString())) && view.getId()==R.id.point)) {
        //如果标志位是FLAG_CALCULATE_FINISH说明刚刚计算结束，此时再次按下数字键将进行清空操作
            if(flag == FLAG_CALCULATE_FINISH)  clear();
            if(flag== FLAG_EMPTY){
                //flag为空表示是第一次输入，直接将输入内容显示即可
                flag = FLAG_NOT_EMPTY;
                value1 = ((Button)view).getText().toString();
                answerValue.setText(value1);
            } else if(flag == FLAG_NOT_EMPTY) {
                //不为空则将输入内容追加到已有内容后面
                //此标志出现时表示尚未输入任何符号，因此和FLAG_EMPTY标志的处理类似
                value1 += ((Button)view).getText().toString();
                answerValue.setText(value1);
            } else {
                //其他标志表示已经输入了符号，因此除了追加数字到现有内容后面外，还要设置value2的值
                String num = ((Button)view).getText().toString();
                value2 = value2 + num;
                answerText = answerValue.getText().toString();
                if(flag == FLAG_POWER_ROOT) {
                    //开方单独处理
                    //如果value2是0则不处理
                    if("0".equals(value2)) {
                        answerValue.setText(answerText  + 0);
                    } else {
                        answerValue.setText(answerText  + num);
                    }
                } else {
                    answerValue.setText(answerText  + num);
                }
            }
        }
    }
    
    private void initView() {
        value1 = "";
        value2 = "";
        num0 = (Button)findViewById(R.id.num0);
        num1 = (Button)findViewById(R.id.num1);
        num2 = (Button)findViewById(R.id.num2);
        num3 = (Button)findViewById(R.id.num3);
        num4 = (Button)findViewById(R.id.num4);
        num5 = (Button)findViewById(R.id.num5);
        num6 = (Button)findViewById(R.id.num6);
        num7 = (Button)findViewById(R.id.num7);
        num8 = (Button)findViewById(R.id.num8);
        num9 = (Button)findViewById(R.id.num9);
        plus = (Button)findViewById(R.id.plus);
        minus = (Button)findViewById(R.id.minus);
        multiply = (Button)findViewById(R.id.multiply);
        divide = (Button)findViewById(R.id.divide);
        equal = (Button)findViewById(R.id.equal);
        point = (Button)findViewById(R.id.point);
        power = (Button)findViewById(R.id.power);
        powerRoot = (Button)findViewById(R.id.power_root);
        sin = (Button)findViewById(R.id.sin);
        cos = (Button)findViewById(R.id.cos);
        tan = (Button)findViewById(R.id.tan);
        nLoop = (Button)findViewById(R.id.factorial);
        backspace = (Button)findViewById(R.id.backspace);
        answerValue = (TextView)findViewById(R.id.answer);
        answerValue.setMovementMethod(ScrollingMovementMethod.getInstance());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(Constants.MENU_GROUP_GENERAL_CALCULATOR,Constants.MENU_GENERAL_CALCULATOR_CLEAR_FOR_GENERAL_CALCULATOR, 1, R.string.clear).setIcon(R.drawable.empty);
        menu.add(Constants.MENU_GROUP_GENERAL_CALCULATOR,Constants.MENU_GENERAL_CALCULATOR_SETTING, 2, R.string.menu_setting).setIcon(R.drawable.setting);
        menu.add(Constants.MENU_GROUP_GENERAL_CALCULATOR,Constants.MENU_GENERAL_CALCULATOR_RETURN_TO_LAST_ACTIVITY, 3, R.string.return_last_activity).setIcon(R.drawable.back);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case Constants.MENU_GENERAL_CALCULATOR_CLEAR_FOR_GENERAL_CALCULATOR:
                clear();
                return true;
            case Constants.MENU_GENERAL_CALCULATOR_SETTING:
                startActivity(new Intent(SeniorCalcActivity.this, SeniorCalcSettingActivity.class));
                this.finish();
                return true;
            case Constants.MENU_GENERAL_CALCULATOR_RETURN_TO_LAST_ACTIVITY:
                this.finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void clear() {
        answerValue.setText("");
        answerValue.scrollTo(0, 0);
        value1="";
        value2="";
        answer = "";
        flag= FLAG_EMPTY;
    }

    @Override
	public void onResume() {
    	Log.d(TAG, "onResume");
//    	flag = mPrivatePreferences.getInt("flag", FLAG_EMPTY);
//		value1 = mPrivatePreferences.getString("value1","");
//		value2 = mPrivatePreferences.getString("value2","");
//		flag2 = mPrivatePreferences.getInt("flag2", FLAG_DELETE);
//		answerValue.setText(mPrivatePreferences.getString("answerValue",""));
		super.onResume();
	}
    
    public void onPause() {
    	Log.d(TAG, "onPause");
//    	Editor editor = mPrivatePreferences.edit();
//    	editor.putInt("flag", flag);
//    	editor.putString("answerValue", answerValue.getText().toString());
//    	editor.putString("value1", value1);
//    	editor.putString("value2", value2);
//    	editor.putInt("flag2", flag2);
//    	editor.commit();
    	super.onPause();
    }

	/**
	 * 默认按了back键后将关闭现有Activity
	 * sdk>2.0
	 */
	public void onBackPressed() {
		Log.d(TAG, "back key pressed!");
		super.onBackPressed();
	}

	/**
	 * 点击home键、程序运行过程中突然来电话等意外情况或屏幕方向改变
	 */
	protected void onSaveInstanceState(Bundle outState) {
		Log.d(TAG, "onSaveInstanceState");
		outState.putInt("flag", flag);
		outState.putString("answerValue", answerValue.getText().toString());
		outState.putString("value1", value1);
		outState.putString("value2", value2);
		outState.putInt("flag2", flag2);
		super.onSaveInstanceState(outState);
	}

	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		Log.d(TAG, "onRestoreInstanceState");
		flag = savedInstanceState.getInt("flag");
		value1 = savedInstanceState.getString("value1");
		value2 = savedInstanceState.getString("value2");
		flag2 = savedInstanceState.getInt("flag2");
		answerValue.setText(savedInstanceState.getString("answerValue"));
		super.onRestoreInstanceState(savedInstanceState);
	}
	
}